package com.chaos.system.controller;


import com.chaos.framework.model.dto.IDS;
import com.chaos.framework.model.dto.result.list.ListResult;
import com.chaos.framework.starter.base.BaseController;
import com.chaos.system.data.RbacMenuData;
import com.chaos.system.data.RbacRoleMenuBtnData;
import com.chaos.system.data.RbacUserRoleData;
import com.chaos.system.dto.RbacMenuRouteDto;
import com.chaos.system.dto.RbacRoleMenuBtnDto;
import com.chaos.system.service.RbacMenuService;
import com.chaos.system.service.RbacRoleMenuBtnService;
import com.chaos.system.service.RbacUserRoleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import jakarta.annotation.Resource;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.*;

/**
 * @author Jacky.Cui
 * @since 2024-11-13
 */
@Slf4j
@RestController
@Api(tags = "")
@RequestMapping("/rbacMenu")
public class RbacMenuRouteController extends BaseController<RbacMenuRouteDto> {
    @Resource
    private RbacMenuService rbacMenuService;
    @Resource
    private RbacUserRoleService rbacUserRoleService;
    @Resource
    private RbacRoleMenuBtnService rbacRoleMenuBtnService;

    @PostMapping("/routes.admin")
    @ApiOperation(value = "获取路由", httpMethod = "POST")
    public ListResult<RbacMenuRouteDto> routes() {
        Long adminId = getAdminId();

        List<RbacUserRoleData> roles = rbacUserRoleService.selectByData(RbacUserRoleData.builder()
                .userId(adminId)
                .build());

        Set<Long> roleIds = roles.stream().map(RbacUserRoleData::getRoleId).collect(Collectors.toSet());
        if (roleIds.isEmpty()) {
            return listResult(List.of());
        }
        Set<Long> menuIds;
        if (isSuperAdminRolePresent(roleIds)) {
            List<RbacMenuData> menus = rbacMenuService.selectByData(RbacMenuData.builder().build());
            menuIds = menus.stream().map(RbacMenuData::getId).collect(Collectors.toSet());
        } else {
            RbacRoleMenuBtnDto query = RbacRoleMenuBtnDto.builder()
                    .roleIds(roleIds)
                    .correlationType(1)
                    .build();
            List<RbacRoleMenuBtnData> menus = rbacRoleMenuBtnService.selectByData(query);
            menuIds = menus.stream().map(RbacRoleMenuBtnData::getMenuOrBtnId).collect(Collectors.toSet());
        }

        if (menuIds.isEmpty()) {
            return listResult(List.of());
        }
        List<RbacMenuData> menuList = rbacMenuService.selectByIds(
                IDS.builder().ids(menuIds).build()
        );
        if (menuList.isEmpty()) {
            return listResult(List.of());
        }

        List<RbacMenuRouteDto> routes = convertToAntDesignRoutes(menuList);

        return listResult(routes);


    }

    private boolean isSuperAdminRolePresent(Set<Long> roleIds) {
        Long superAdminRoleId = 1L;
        return roleIds.contains(superAdminRoleId);
    }


    private List<RbacMenuRouteDto> convertToAntDesignRoutes(List<RbacMenuData> menuList) {
        // 创建一个 map 以便通过 parentId 快速查找子菜单
        Map<Long, List<RbacMenuData>> menuMap = new HashMap<>();
        for (RbacMenuData menu : menuList) {
            menuMap.computeIfAbsent(menu.getParentId(), k -> new ArrayList<>()).add(menu);
        }

        // 找到所有顶级菜单项
        List<RbacMenuRouteDto> routes = new ArrayList<>();
        for (RbacMenuData menu : menuList) {
            if (menu.getParentId() == null || menu.getParentId() == 0) {
                addRoute(menuMap, routes, menu);
            }
        }

        return routes;
    }

    // 递归构建子路由
    private List<RbacMenuRouteDto> buildChildRoutes(Long parentId, Map<Long, List<RbacMenuData>> menuMap) {
        List<RbacMenuRouteDto> childRoutes = new ArrayList<>();
        List<RbacMenuData> children = menuMap.getOrDefault(parentId, Collections.emptyList());
        for (RbacMenuData menu : children) {
            addRoute(menuMap, childRoutes, menu);
        }
        return childRoutes;
    }

    private void addRoute(Map<Long, List<RbacMenuData>> menuMap, List<RbacMenuRouteDto> routes, RbacMenuData menu) {
        RbacMenuRouteDto route = new RbacMenuRouteDto();
        route.setPath(menu.getPath());
        route.setName(menu.getName());
        route.setComponent(menu.getComponent());
        route.setExact(menu.isExact());
        route.setIcon(menu.getIcon());
        route.setRedirect(menu.getRedirect());
        route.setRoutes(buildChildRoutes(menu.getId(), menuMap));
        routes.add(route);
    }


}
